<?php


namespace XinYaTable\Forms\Models;


use Illuminate\Database\Eloquent\Model;

class BaseModel extends Model
{
    /**
     * unix : unix timestamp 13 length
     *
     * @var string default:unix
     */
    protected $dateFormat = 'unix';

    /**
     * @var array 默认列表字段
     */
    protected $defaultListFields = ['*'];
    
    /**
     * @var array
     */
    protected $searchable = [];

    /**
     * 添加精度字段类型转换 $cast => ['field1'=> 'round:2' ]
     *
     * @param string $key
     * @param mixed  $value
     *
     * @return float|mixed
     */
    protected function castAttribute($key, $value)
    {
        $type = $this->getCastType($key);
        if (stripos($type, 'round') !== false) {
            $_tempRound = explode(':', $type);

            return round($value, $_tempRound[1] ?? 2);
        }

        return parent::castAttribute($key, $value);
    }


    /**
     * Convert a DateTime to a storable string.
     *
     * @param  \DateTime|int $value
     *
     * @return string
     */
    public function fromDateTime($value)
    {
        if ($this->_isUnixDateTime()) {
            if (!is_numeric($value) && !empty($value)) {
                return $this->formatUnixTimestamp($value);
            } else {
                return $value;
            }
        }

        return empty($value)
            ? $value
            : $this->asDateTime($value)->format($this->getDateFormat());
    }

    /**
     * @param $value
     *
     * @return int
     */
    protected function formatUnixTimestamp($value): int
    {
        return (int)($this->asDateTime($value)->format('Uu') / 1000);
    }


    /**
     * Return a timestamp as DateTime object.
     *
     * @param  mixed $value
     *
     * @return \Illuminate\Support\Carbon
     */
    protected function asDateTime($value)
    {
        if ($this->_isUnixDateTime()) {
            return $value;
        }

        return parent::asDateTime($value);
    }


    /**
     * Add the casted attributes to the attributes array.
     *
     * @param  array $attributes
     * @param  array $mutatedAttributes
     *
     * @return array
     */
    protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
    {
        foreach ($this->getCasts() as $key => $value) {
            if (!array_key_exists($key, $attributes) || in_array($key, $mutatedAttributes)) {
                continue;
            }

            // Here we will cast the attribute. Then, if the cast is a date or datetime cast
            // then we will serialize the date for the array. This will convert the dates
            // to strings based on the date format specified for these Eloquent models.
            $attributes[$key] = $this->castAttribute(
                $key, $attributes[$key]
            );

            // If the attribute cast was a date or a datetime, we will serialize the date as
            // a string. This allows the developers to customize how dates are serialized
            // into an array without affecting how they are persisted into the storage.
            if ($attributes[$key] &&
                ($value === 'date' || $value === 'datetime')) {
                if (!$this->_isUnixDateTime()) {
                    $attributes[$key] = $this->serializeDate($attributes[$key]);
                }
            }
        }

        return $attributes;
    }


    /**
     * Add the date attributes to the attributes array.
     *
     * @param  array $attributes
     *
     * @return array
     */
    protected function addDateAttributesToArray(array $attributes)
    {
        foreach ($this->getDates() as $key) {
            if (!isset($attributes[$key])) {
                continue;
            }

            if ($this->_isUnixDateTime()) {

                $attributes[$key] = $this->asDateTime($attributes[$key]);
            } else {
                $attributes[$key] = $this->serializeDate(
                    $this->asDateTime($attributes[$key])
                );
            }
        }

        return $attributes;
    }

    /**
     * @return bool
     */
    private function _isUnixDateTime(): bool
    {
        return strtolower($this->getDateFormat()) == 'unix';
    }
    

    /**
     * @param $query
     *
     * @return mixed
     */
    public function scopeDefaultFields($query)
    {
        return $query->select($this->defaultListFields);
    }
}